/*
 * @Description: 流程组件
 * @Author: DHL
 * @Date: 2022-12-23 13:52:43
 * @LastEditors: DHL
 * @LastEditTime: 2024-02-07 09:23:37
 */

import { defineComponent, onMounted } from 'vue'
import { ElMessage } from 'element-plus'
import { cloneDeep, debounce, merge } from 'lodash-es'
import { apiFlowGetProcessInstance, apiFlowProcessPreview } from '@/api/flow/flowProcess'
import { FlowUserTaskModel } from '@/api/flow/model/flowUserTaskModel'
import {
  apiFlowTaskBack,
  apiFlowTaskComplete,
  apiFlowTaskDelegate,
  apiFlowTaskReject,
  apiFlowTaskRevoke,
  apiFlowTaskTurn
} from '@/api/flow/flowTask'
import { isNotEmpty, isEmpty } from '@/utils/isUtils'
import { useLoginUserStore } from '@/store/modules/loginUser'
import useCacheData from '@/hooks/web/cacheData'
import { UserModel } from '@/api/system/model/userModel'
import selectUser from '@/pages/components/selectUser.vue'
import twFlowBack from './twFlowBack.vue'
import twFlowchartPopup from '@/pages/flow/twFlow/twFlowchart/twFlowchartPopup.vue'
import twFlowConfig from './twFlowConfig/index.vue'

export default defineComponent({
  name: 'TwFlow',
  components: { selectUser, twFlowBack, twFlowchartPopup, twFlowConfig },
  props: {
    loading: {
      type: Boolean,
      default: 'false'
    },

    /**
     * 流程名称
     */
    procName: {
      type: String,
      required: true
    },

    /**
     * 流程定义KEY
     */
    procDefKey: {
      type: String,
      required: true
    },

    /**
     * 业务标识
     */
    businessKey: {
      type: String,
      default: ''
    },

    /**
     * 流程变量
     */
    values: {
      type: Object,
      default: {}
    },

    /**
     * 表单数据
     */
    formData: {
      type: Object,
      default: {}
    },
    /**
     * 操作类型
     * add - 新增
     * edit - 编辑
     * view - 查看
     * approval - 审批
     */
    action: {
      type: String,
      default: 'add'
    }
  },
  emits: ['submit', 'reset', 'formDisabled', 'update:loading'],
  setup(props, { emit, expose }) {
    //////////////////////////////////////////////////
    // 属性
    //////////////////////////////////////////////////

    const bodyRef = ref()
    const footerRef = ref()

    /**
     * 是否加载最新流程
     */
    const latestVersion = ref(false)

    const bodyStyle = reactive({
      height: '100%'
    })

    const { getDicName } = useCacheData()

    //////////////////////////////////////////////////
    // Store
    //////////////////////////////////////////////////
    /**
     * 当前登录用户
     */
    const loginUserStore = useLoginUserStore()

    //////////////////////////////////////////////////
    // watch
    //////////////////////////////////////////////////
    /**
     * 监听表单数据
     * 表单数据改变后，重新加载流程预览
     */
    watch(
      () => [props.formData, props.values],
      () => {
        handleProcessPreview()
      },
      { deep: true }
    )

    /**
     * 监听业务主键
     */
    watch(
      () => [props.businessKey],
      () => {
        taskState.businessKey = props.businessKey
        handleSearchProcessInstance()
        handleProcessPreview()
      },
      { deep: true }
    )

    //////////////////////////////////////////////////
    // computed
    //////////////////////////////////////////////////

    /**
     * 流程审批状态标题
     */
    const approvalTitle = computed(() => {
      let rtn = '制单'

      if (isNotEmpty(procInst.businessStatus)) {
        rtn = getDicName('FLOW_STATE', procInst.businessStatus) || ''
      }

      return rtn
    })

    /**
     * 验证审批按钮
     */
    const verifyApproval = computed(() => {
      let rtn = false

      if (['approval'].includes(props.action)) {
        const loginUserId = loginUserStore.id
        userTaskList.value.forEach((item) => {
          item?.assigneeList?.forEach((assignee) => {
            if (isEmpty(assignee.endTime) && assignee.id === loginUserId) {
              rtn = true
            }
          })
        })
      }

      return rtn
    })

    /**
     * 验证申请按钮
     */
    const verifyApplyFor = computed(() => {
      return ['add', 'edit'].includes(props.action)
    })

    /**
     * 验证撤销按钮
     */
    const verifyRevoke = computed(() => {
      let rtn = false
      if (
        ['edit'].includes(props.action) &&
        isNotEmpty(procInst.businessStatus) &&
        ['SPZ'].includes(procInst.businessStatus) &&
        !procInst.finish
      ) {
        rtn = true
      }
      return rtn
    })

    /**
     * 验证提交按钮
     */
    const verifySubmit = computed(() => {
      let rtn = true

      // 未查询到配置的流程
      if (isEmpty(userTaskList.value)) {
        return false
      }

      if (['SPZ', 'BJ'].includes(procInst.businessStatus)) {
        rtn = false
      }

      // 申请人与登录人不同禁止编辑
      if (isNotEmpty(procInst.startUserId) && loginUserStore.id !== procInst.startUserId) {
        rtn = false
      }

      return rtn
    })

    /**
     * 验证是否可以选择用户
     */
    const verifySelectUser = computed(() => {
      let rtn = false

      if (
        verifyApplyFor.value &&
        (isEmpty(procInst.businessStatus) || ['BH', 'CH'].includes(procInst.businessStatus))
      ) {
        rtn = true
      }
      return rtn
    })

    //////////////////////////////////////////////////
    // 计算布局
    //////////////////////////////////////////////////

    /**
     * 计算布局函数
     */
    function buildBodyStyle() {
      const footerElement: HTMLDivElement = unref(footerRef)
      const footerHeight = footerElement?.offsetHeight
      if (footerHeight) {
        bodyStyle.height = `calc(100% - ${footerHeight}px)`
      }
    }

    //////////////////////////////////////////////////
    // 函数
    //////////////////////////////////////////////////

    //////////////////////////////////////////////////
    // 函数 - 流程预览
    //////////////////////////////////////////////////
    /**
     * 流程预览加载
     */
    const loadingApproval = ref(true)

    /**
     * 加载状态
     */
    const loading = ref(true)

    /**
     * 流程预览 - 用户任务集合
     */
    const userTaskList = ref([] as Array<FlowUserTaskModel>)

    /**
     * 流程实例信息
     */
    const procInst = reactive({
      finish: false,
      deploymentId: '',
      processInstanceId: '',
      businessKey: '',
      businessStatus: '',
      startUserId: ''
    })

    /**
     * 获取流程实例
     */
    function handleSearchProcessInstance() {
      if (isNotEmpty(props.businessKey)) {
        apiFlowGetProcessInstance({
          businessKey: props.businessKey
        }).then((result) => {
          if (result?.success) {
            merge(procInst, result.data)

            handleFormDisabled()
          }
        })
      }
    }

    /**
     * 表单是否禁用
     */
    function handleFormDisabled() {
      if (procInst.businessStatus === 'BJ') {
        emit('formDisabled', true)
      } else if (isNotEmpty(procInst.startUserId) && loginUserStore.id !== procInst.startUserId) {
        emit('formDisabled', true)
      }
    }

    /**
     * 流程预览防抖动定时器
     */
    const processPreviewDebounce = debounce(processPreviewSearch, 1000)

    /**
     * 流程预览查询
     */
    function processPreviewSearch() {
      const submitParams = {
        procDefKey: props.procDefKey,
        businessKey: props.businessKey,
        values: props.values,
        formData: props.formData,
        latestVersion: latestVersion.value
      }

      loading.value = true

      apiFlowProcessPreview(submitParams)
        .then((result) => {
          if (result?.success) {
            userTaskList.value = result.data
          } else {
            ElMessage.error(result?.message)
          }

          nextTick(() => {
            buildBodyStyle()
          })
        })
        .finally(() => {
          loadingApproval.value = false
          loading.value = false
        })
    }

    /**
     * 流程预览
     */
    function handleProcessPreview() {
      processPreviewDebounce()
    }

    /**
     * 获取节点审批名称
     * @param node
     */
    function getNodeName(node: FlowUserTaskModel) {
      let rtn = node.name
      let multiWayShow = false

      // 分配人员有多个人
      if (node.assigneeList && node.assigneeList.length > 0) {
        multiWayShow = true
      }

      if (node.approvalRules) {
        // 发起人自选 - 自选多个人
        if (
          node.approvalRules.assignedRules.type === 'optional' &&
          node.approvalRules.assignedRules.optionalWay === 'more'
        ) {
          multiWayShow = true
        }

        // 连续多级主管
        if (node.approvalRules.assignedRules.type === 'continuousMultistage') {
          multiWayShow = true
        }

        // 直属主管
        if (node.approvalRules.assignedRules.type === 'supervisor') {
          multiWayShow = true
        }

        if (multiWayShow) {
          const multiInstanceApprovalWay = node.approvalRules.multiInstanceRules.approvalWay
          if ('sequential' === multiInstanceApprovalWay) {
            rtn += '（依次审批）'
          } else if ('parallel' === multiInstanceApprovalWay) {
            rtn += '（会签）'
          } else if ('orSign' === multiInstanceApprovalWay) {
            rtn += '（或签）'
          }
        }
      }

      return rtn
    }

    //////////////////////////////////////////////////
    // 函数 - 申请操作
    //////////////////////////////////////////////////

    /**
     * 提交申请
     */
    function handleSubmit() {
      // 流程启动参数
      const processStartParams = {
        latestVersion: latestVersion.value,
        procDefKey: props.procDefKey,
        businessKey: props.businessKey,
        values: props.values,
        userTaskVos: [] as Array<{ id: string; assigneeList: Array<any> }>,
        ccToVos: []
      }

      const assigneeList: Array<any> = []

      // 流程审批人
      if (userTaskList.value && userTaskList.value.length > 0) {
        const psUserTaskList: Array<{ id: string; type: string; assigneeList: Array<any> }> = []
        userTaskList.value.forEach((item) => {
          psUserTaskList.push({
            id: item.id,
            type: item.type,
            assigneeList: item.assigneeList
          })

          if (item.assigneeList) {
            assigneeList.push(...item.assigneeList)
          }
        })
        processStartParams.userTaskVos = psUserTaskList
      }

      if (isEmpty(assigneeList)) {
        ElMessage.warning('请选择审批人')
        return
      }

      emit('submit', processStartParams)
    }

    /**
     * 取消申请
     */
    function handleReset() {
      emit('reset', true)
    }

    //////////////////////////////////////////////////
    // 函数 - 审批操作
    //////////////////////////////////////////////////
    /**
     * 审批提交参数
     */
    const taskState = reactive({
      businessKey: '', // 业务ID
      taskDefKey: '', // 任务节点ID
      opinion: '', // 审批意见
      userId: '' // 用户ID
    })

    /**
     * 同意
     */
    function handleTaskComplete() {
      emit('update:loading', true)

      apiFlowTaskComplete(taskState)
        .then((result) => {
          if (result?.success) {
            handleProcessPreview()
            handleSearchProcessInstance()
            ElMessage.success(result.message)
          } else {
            ElMessage.warning(result?.message)
          }
        })
        .finally(() => {
          emit('update:loading', false)
        })
    }

    /**
     * 撤回
     */
    function handleTaskRevoke() {
      emit('update:loading', true)
      apiFlowTaskRevoke({
        businessKey: props.businessKey
      })
        .then((result) => {
          if (result?.success) {
            handleProcessPreview()
            handleSearchProcessInstance()
            ElMessage.success(result.message)
          } else {
            ElMessage.warning(result?.message)
          }
        })
        .finally(() => {
          emit('update:loading', false)
        })
    }

    /**
     * 驳回
     */
    function handleTaskReject() {
      if (isEmpty(taskState.opinion)) {
        ElMessage.warning('请填写驳回意见')
        return
      }
      emit('update:loading', true)
      apiFlowTaskReject(taskState)
        .then((result) => {
          if (result?.success) {
            handleProcessPreview()
            handleSearchProcessInstance()
            ElMessage.success(result.message)
          } else {
            ElMessage.error(result?.message)
          }
        })
        .finally(() => {
          emit('update:loading', false)
        })
    }

    /**
     * 转办
     */
    function handleTaskTurn(turnUser: UserModel) {
      if (isEmpty(turnUser.id)) {
        ElMessage.warning('请选择转办用户')
        return
      }

      taskState.userId = turnUser.id
      emit('update:loading', true)
      apiFlowTaskTurn(taskState)
        .then((result) => {
          if (result?.success) {
            handleProcessPreview()
            handleSearchProcessInstance()
            ElMessage.success(result.message)
          } else {
            ElMessage.error(result?.message)
          }
        })
        .finally(() => {
          emit('update:loading', false)
        })
    }

    /**
     * 委派
     */
    function handleTaskDelegate(delegateUser: UserModel) {
      if (isEmpty(delegateUser.id)) {
        ElMessage.warning('请选择委派用户')
        return
      }

      taskState.userId = delegateUser.id
      emit('update:loading', true)
      apiFlowTaskDelegate(taskState)
        .then((result) => {
          if (result?.success) {
            handleProcessPreview()
            handleSearchProcessInstance()
            ElMessage.success(result.message)
          } else {
            ElMessage.error(result?.message)
          }
        })
        .finally(() => {
          emit('update:loading', false)
        })
    }

    //////////////////////////////////////////////////
    // 退回
    //////////////////////////////////////////////////
    const twFlowBackRef = ref()

    /**
     * 打开退回窗口
     */
    function handleOpenBack() {
      if (isEmpty(taskState.opinion)) {
        ElMessage.warning('请填写退回意见')
        return
      }
      twFlowBackRef.value.handleOpen(taskState)
    }

    /**
     * 退回
     * @param taskDefKey  退回的节点
     */
    function handleSubmitBack(taskDefKey: string) {
      taskState.taskDefKey = taskDefKey

      emit('update:loading', true)
      apiFlowTaskBack(taskState)
        .then((result) => {
          if (result?.success) {
            handleProcessPreview()
            handleSearchProcessInstance()
            ElMessage.success(result.message)
          } else {
            ElMessage.error(result?.message)
          }
        })
        .finally(() => {
          twFlowBackRef.value.handleReset()
          emit('update:loading', false)
        })
    }

    //////////////////////////////////////////////////
    // 流程图
    //////////////////////////////////////////////////
    const twFlowchartPopupRef = ref()

    /**
     * 预览流程图
     */
    function handleOpenFlowChart() {
      if (isEmpty(userTaskList.value)) {
        ElMessage.warning('未获取到流程部署信息')
        return
      }

      const userTask = userTaskList.value[0] as FlowUserTaskModel

      const params = {
        procInstId: null,
        deploymentId: userTask.deploymentId
      }

      if (userTask.deploymentId === procInst.deploymentId) {
        Object.assign(params, {
          procInstId: procInst.processInstanceId,
          deploymentId: null
        })
      }

      twFlowchartPopupRef.value.handleOpen(params)
    }

    //////////////////////////////////////////////////
    // 流程配置
    //////////////////////////////////////////////////
    const twFlowConfigRef = ref()

    /**
     * 流程配置弹框
     */
    function handleOpenFlowConfig() {
      twFlowConfigRef.value.handleOpen({ name: props.procName, key: props.procDefKey })
    }

    //////////////////////////////////////////////////
    // 用户任务状态样式
    //////////////////////////////////////////////////
    /**
     * 根据用户任务状态显示不同的一颜色
     * @param userTask
     */
    function getUserTaskClass(userTask) {
      if (isEmpty(procInst.processInstanceId)) {
        return 'primary'
      }

      let rtn = ''

      if (['SP', 'WC', 'XTZX'].includes(userTask.commentType)) {
        rtn = 'primary'
      } else if (userTask.commentType == 'SPZ') {
        rtn = 'warning'
      } else if (userTask.commentType == 'DSP' || isEmpty(userTask.commentType)) {
        rtn = 'info'
      } else if (userTask.commentType == 'CC') {
        rtn = 'success'
      } else {
        rtn = 'error'
      }

      return rtn
    }

    /**
     * 获取tag类型
     */
    function getUserTaskTag(userTask) {
      const type = getUserTaskClass(userTask)
      return type
    }

    //////////////////////////////////////////////////
    // 选择用户
    //////////////////////////////////////////////////

    /**
     * 用户选择
     */
    const selectUserRef = ref()

    /**
     * 选择用户类型
     * optional - 审批节点自选审批人
     * turn - 转办
     */
    let selectUserType = ''

    /**
     * 审批节点选择用户
     * 当前操作的节点
     */
    let activeUserTask: FlowUserTaskModel = {} as FlowUserTaskModel

    /**
     * 弹出选择用户
     */
    function handleSelectUserOpen(params: any) {
      selectUserType = params.type

      if ('optional' === selectUserType) {
        activeUserTask = params.userTask as FlowUserTaskModel
        selectUserRef.value.handleOpen(activeUserTask.assigneeList)
      } else if ('turn' === selectUserType) {
        if (isEmpty(taskState.opinion)) {
          ElMessage.warning('请填写转办意见')
          return
        }
        selectUserRef.value.handleOpen([])
      } else if ('delegate' === selectUserType) {
        if (isEmpty(taskState.opinion)) {
          ElMessage.warning('请填写委派意见')
          return
        }
        selectUserRef.value.handleOpen([])
      }
    }

    /**
     * 选择用户确认
     * @param userList
     */
    function handleSubmitSelectUser(userList: Array<UserModel>) {
      if ('optional' === selectUserType) {
        setAssigneeList(userList)
      } else if ('turn' === selectUserType) {
        if (userList && userList.length > 1) {
          ElMessage.warning('只能选择一个用户')
          return
        }
        handleTaskTurn(userList[0])
      } else if ('delegate' === selectUserType) {
        if (userList && userList.length > 1) {
          ElMessage.warning('只能选择一个用户')
          return
        }
        handleTaskDelegate(userList[0])
      }
    }

    /**
     * 审批节点选择用户,设置审批人
     */
    function setAssigneeList(userList) {
      // 发起人自选 - 自选一个人
      if (
        activeUserTask.approvalRules.assignedRules.type === 'optional' &&
        activeUserTask.approvalRules.assignedRules.optionalWay === 'one' &&
        userList &&
        userList.length > 1
      ) {
        ElMessage.warning('只能选择一个用户')
        return
      }

      activeUserTask.assigneeList = cloneDeep(userList)
    }

    /**
     * 清空选择用户
     */
    function handleClearUser() {}

    /**
     * 删除用户
     * @param user
     */
    function handleDeleteUser(user) {}

    //////////////////////////////////////////////////
    // 更多操作按钮
    //////////////////////////////////////////////////

    /**
     * 更多操作
     * @param command
     */
    function handleMoreCommand(command: string) {
      switch (command) {
        case 'flowChart':
          handleOpenFlowChart()
          break

        case 'flowConfig':
          handleOpenFlowConfig()
          break

        case 'back':
          handleOpenBack()
          break

        case 'delegate':
          handleSelectUserOpen({ type: 'delegate' })
          break

        case 'turn':
          handleSelectUserOpen({ type: 'turn' })
          break

        default:
          break
      }
    }

    //////////////////////////////////////////////////
    // 生命周期
    //////////////////////////////////////////////////
    onMounted(() => {
      nextTick(() => {
        buildBodyStyle()

        handleProcessPreview()
        handleSearchProcessInstance()
      })
    })

    return {
      bodyRef,
      footerRef,
      userTaskList,
      bodyStyle,
      latestVersion,
      procInst,
      handleProcessPreview,
      getNodeName,
      handleSubmit,
      handleReset,
      handleTaskComplete,
      handleTaskRevoke,
      handleTaskReject,
      twFlowBackRef,
      handleOpenBack,
      handleSubmitBack,
      twFlowchartPopupRef,
      handleOpenFlowChart,
      selectUserRef,
      handleSelectUserOpen,
      handleSubmitSelectUser,
      handleClearUser,
      handleDeleteUser,
      verifyApproval,
      verifyApplyFor,
      verifyRevoke,
      verifySubmit,
      verifySelectUser,
      loadingApproval,
      loading,
      approvalTitle,
      taskState,
      getUserTaskClass,
      getUserTaskTag,
      handleMoreCommand,
      twFlowConfigRef
    }
  }
})
